#pragma once

#include <cassert>
#include <string>


 

struct Reg {
    unsigned id;

    explicit Reg(unsigned i) : id(i) { assert(i <= 31); }
    bool operator==(const Reg &other) { return id == other.id; }

    std::string print() const;

    static Reg zero() { return Reg(0); }
    static Reg ra() { return Reg(1); }
    static Reg sp() { return Reg(2); }
    static Reg fp() { return Reg(8); }
    static Reg a(unsigned i) {
        assert(0 <= i and i <= 7);
        return Reg(i + 10);
    }
    static Reg t(unsigned i) {
        assert(0 <= i and i <= 6);
        if(i < 3) 
            return Reg(i + 5);
        else
            return Reg(i + 25);
    }
    static Reg s(unsigned i) {
        assert(0 <= i and i <= 11);
        if (i < 2)
            return Reg(i + 8);
        else
            return Reg(i + 16);
    }
};

struct FReg {
    unsigned id;

    explicit FReg(unsigned i) : id(i) { assert(i <= 31); }
    bool operator==(const FReg &other) { return id == other.id; }

    std::string print() const;

    static FReg fa(unsigned i) {
        assert(0 <= i and i <= 7);
        return FReg(i + 10);
    }
    static FReg ft(unsigned i) {
        assert(0 <= i and i <= 15);
        if (i >= 12) return FReg(i + 12);
        else if (i >= 8) return FReg(i + 20);
        else return FReg(i);
    }
    static FReg fs(unsigned i) {
        assert(0 <= i and i <= 7);
        if (i <= 1) return FReg(i + 8);
        else return FReg(i + 16);
    }
};

